<script setup lang="ts" name="app">
import searchBar from './components/search.vue'
import { eventBus, searchPlugins, searchWinPlugins } from '@/utils'
import pinyin from 'pinyin-match'

let clipboardItemBank: IClipboardItem | undefined
const clipboardItem = ref<IClipboardItem>()

const searchBarIns = ref<InstanceType<typeof searchBar> | null>()
const searchBarVal = ref<string>('')

const curPlugin = ref<plugin.PluginElem>()
const resultArea = ref<HTMLElement | null>()

const winState = ref<WinState>()

const elements = ref<{
  plugins?: plugin.Plugin[]
  apps?: AppInfo[]
}>({})

interface DisplayResultItem {
  title: string
  icon?: unknown
  searchResult: SearchResult
}

const displayResult = computed(() => {
  if (curPlugin.value) {
    return []
  }

  const ret: DisplayResultItem[] = []

  //应用搜索
  const searchInfo = clipboardItem.value ?? searchBarVal.value ?? ''
  if (searchInfo !== '') {
    const plugins = searchPlugins(toRaw(elements.value.plugins ?? []), searchInfo)
    // console.log('searchInfo', searchInfo, plugins)
    //搜索应用
    if (typeof searchInfo === 'string') {
      const b = plugins
        .filter((p) => typeof p.cmd === 'string')
        .map(
          (p) =>
            ({
              ...p,
              type: 'plugin'
            }) as SearchResultItem
        )

      const a =
        elements.value.apps
          ?.filter((app) => pinyin.match(app.name, searchInfo))
          .map(
            (app) =>
              ({
                type: 'app',
                name: app.name,
                path: app.path,
                icon: app.icon
              }) as SearchResultItem
          ) ?? []
      b.push(...a)

      if (b.length > 0) {
        b.forEach((item) => {
          if (item.type === 'plugin') {
            const result = pinyin.match(item.label, searchInfo)
            if (result) {
              item.from = result[0]
              item.to = result[1]
            }
          } else if (item.type === 'app') {
            const result = pinyin.match(item.name, searchInfo)
            if (result) {
              item.from = result[0]
              item.to = result[1]
            }
          }
        })

        ret.push({
          title: '搜索结果',
          searchResult: b
        })
      }

      const match = plugins.filter((p) => typeof p.cmd !== 'string')
      if (match.length > 0) {
        ret.push({
          title: '搜索匹配',
          searchResult: match.map(
            (p) =>
              ({
                ...p,
                type: 'plugin'
              }) as SearchResultItem
          )
        })
      }
    } else {
      console.log('searchInfo is not string', searchInfo)

      let matchResult = plugins.map(
        (p) =>
          ({
            ...p,
            type: 'plugin'
          }) as SearchResultItem
      )

      if (searchBarVal.value !== '') {
        matchResult = matchResult.filter((item) => {
          if (item.type === 'plugin') {
            const result = pinyin.match(item.label, searchBarVal.value)
            if (result) {
              item.from = result[0]
              item.to = result[1]
            }
            return result
          }
          return false
        })
      }
      if (matchResult.length > 0) {
        ret.push({
          title: '搜索匹配',
          searchResult: matchResult
        })
      }
    }
  }

  if (searchBarVal.value === '' && winState.value) {
    const winPlugins = searchWinPlugins(toRaw(elements.value.plugins ?? []), winState.value)
    if (winPlugins.length > 0) {
      ret.push({
        title: winState.value.appName + ' 窗口',
        searchResult: winPlugins.map(
          (p) =>
            ({
              ...p,
              type: 'plugin'
            }) as SearchResultItem
        )
      })
    }
  }

  //窗口
  return ret
})

watch(
  () => [displayResult.value, curPlugin.value],
  async () => {
    await nextTick()
    if (!curPlugin.value) {
      window.api.msgTrigger('setExpandHeight', resultArea.value?.scrollHeight || 0)
    }
  }
)

//选中区域索引编号
const activeSectionIndex = ref<number>(0)

const goBack = () => {
  if (searchBarVal.value !== '') {
    searchBarVal.value = ''
    return false
  }

  if (curPlugin.value) {
    exitPlugin()
    return false
  }

  if (clipboardItem.value) {
    clipboardItem.value = undefined
    return false
  }

  return true
}

const exitPlugin = () => {
  if (curPlugin.value) {
    window.api.msgTrigger('exitPlugin')
    curPlugin.value = undefined
    searchBarVal.value = ''
  }
}

const open = (item: SearchResultItem) => {
  console.log('open', item)
  if (item.type === 'app') {
    searchBarVal.value = ''
    window.api.msgTrigger('open', item.path)
    window.api.msgTrigger('show', { isHide: true })
  } else if (item.type === 'plugin') {
    curPlugin.value = item
    if (typeof item.cmd !== 'string' && item.cmd.type !== 'window') {
      clipboardItem.value = undefined
    }
    window.api.msgTrigger('openPlugin', item, true)
    searchBarVal.value = ''
  }

  // 命令
  // else if (item.type === 'cmd') {
  //   if (item.path === 'copyPath') {
  //     window.electron.clipboard.writeText(
  //       winState.value?.finderDir ?? window.electron.app.getPath('desktop')
  //     )
  //   } else if (item.path === 'openInTerminal') {
  //     // window.electron.ipcRenderer.send('open-in-terminal', clipboardItemBank?.path)

  //     window.electron.ipcRenderer.send(
  //       'open-in-terminal',
  //       winState.value?.finderDir ?? window.electron.app.getPath('desktop')
  //     )
  //   } else if (item.path === 'newFile') {
  //     console.log('new file')

  //     // window.electron.ipcRenderer.send(
  //     //   'new-file',
  //     //   winState.value?.finderDir ?? window.electron.app.getPath('desktop')
  //     // )
  //   }
}

const handleMouseUp = () => {
  nextTick(() => {
    searchBarIns.value?.focus()
  })
}

//每次搜索变更则更新焦点选区1
watch(
  () => searchBarVal.value,
  () => {
    activeSectionIndex.value = 0
    elements.value = window.api.msgTrigger('elements', undefined, true)
  }
)

// 使用 sendHeight 函数代替直接调用
onMounted(async () => {
  eventBus.on('sectionChange', (event) => {
    const data = event as selectChangeData
    let val = activeSectionIndex.value + (displayResult.value.length || 1)
    if (data.action === 'right' || data.action === 'down') {
      val += 1
    } else {
      val -= 1
    }
    val = val % (displayResult.value.length || 1)
    activeSectionIndex.value = val
    data.curSectionIndex = val
    eventBus.emit('selectChange', data)
  })

  // //窗口自适应
  // if (resultArea.value) {
  //   // 创建 MutationObserver 实例
  //   const observer = new MutationObserver(() => {
  //     if (curPlugin.value) {
  //       return
  //     }
  //     // const height = resultArea.value?.scrollHeight || 0
  //     // window.electron.ipcRenderer.send('set-height', height)
  //   })
  //   const config = { childList: true, subtree: true, CharacterData: true }
  //   observer.observe(resultArea.value, config)
  // }

  //监听esc按键
  window.addEventListener('keydown', (e) => {
    if (e.code === 'Escape') {
      e.preventDefault()
      if (goBack()) {
        window.api.msgTrigger('show', { isHide: true })
      }
    }

    //item焦点移动
    const keyToDirection = {
      Tab: (e) => ({
        action: e.shiftKey ? 'left' : 'right',
        prevent: true
      }),
      ArrowLeft: () => ({
        action: 'left'
        // checkBlock: true
      }),
      ArrowRight: () => ({
        action: 'right'
        // checkBlock: true
      }),
      ArrowUp: () => ({
        action: 'up',
        prevent: true
      }),
      ArrowDown: () => ({
        action: 'down',
        prevent: true
      })
    }
    if (keyToDirection[e.code]) {
      const action = keyToDirection[e.code](e)
      if (action.prevent) {
        e.preventDefault()
      }

      if (!action.checkBlock || searchBarIns.value?.cursorMoveBlock(action.action)) {
        selectChange(action.action)
      }
    }

    //回车
    if (e.code === 'Enter') {
      e.preventDefault()
      eventBus.emit('selectItem')
    }

    if (e.code === 'Backspace') {
      //获取光标位置
      if (searchBarIns.value?.cursorMoveBlock('left')) {
        searchBarVal.value = ''
        goBack()
      }
    }
  })

  //监听dbclick
  window.addEventListener('dblclick', () => {
    //TODO 切换最近使用 展示开关
  })
})

const selectChange = (action: MoveAction) => {
  eventBus.emit('selectChange', {
    startSectionIndex: activeSectionIndex.value,
    action
  } as selectChangeData)
}

window.stools = {
  hooks: {
    onShow: () => {
      searchBarIns.value?.focus(true)
      winState.value = window.api.getGlobal('winState') as WinState
      elements.value = window.api.msgTrigger('elements', {}, true)
      console.log('show', winState.value, toRaw(elements.value))
      const clipboardItemNow = window.api.getGlobal('clipboardItem') as IClipboardItem
      const now = Date.now()
      if (!clipboardItemNow || (now - clipboardItemNow.copyTime) / 1000 > 60) {
        clipboardItem.value = undefined
        console.log('copy time out')
        return
      }
      if (clipboardItemBank?.id !== clipboardItemNow.id) {
        if (clipboardItemNow.type === 'text') {
          //去前后换行空格
          clipboardItemNow.content = clipboardItemNow.content.replace(/(^\s*)|(\s*$)/g, '')
          if (!clipboardItemNow.content.includes('\n')) {
            clipboardItem.value = undefined
            searchBarVal.value = clipboardItemNow.content
            clipboardItemBank = clipboardItemNow
            return
          }
        }
        searchBarVal.value = ''
        clipboardItemBank = clipboardItemNow
        clipboardItem.value = clipboardItemNow
      }
    },
    onExitPlugin: () => {
      if (curPlugin.value) {
        exitPlugin()
      }
    },
    onHide: () => {
      winState.value = undefined
    }
  }
}
</script>

<template>
  <div class="flex flex-col h-full select-none box-border" @mouseup="handleMouseUp">
    <searchBar
      ref="searchBarIns"
      v-model:searchVal="searchBarVal"
      :clipboard-item="clipboardItem"
      :cur-plugin="curPlugin"
      @go-back="goBack"
    />

    <div ref="resultArea" class="result cus-scroll-y pr-4px mr-2px">
      <result
        v-for="(item, index) in displayResult"
        :key="item.title + index"
        :title="item.title"
        :search-result="item.searchResult"
        :section-index="index"
        :active-index="activeSectionIndex"
        :search-bar-val="searchBarVal"
        @open="open"
      ></result>
    </div>
  </div>
</template>

<style lang="scss"></style>
./utils
